package team.seekers.oj.homework.service;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.oj.auth.enums.PermissionEnum;
import team.seekers.oj.common.entity.PageResult;
import team.seekers.oj.common.entity.UserSessionDTO;
import team.seekers.oj.common.enums.ApiExceptionEnum;
import team.seekers.oj.common.exception.ApiException;
import team.seekers.oj.common.util.AssertUtils;
import team.seekers.oj.common.util.RedisUtils;
import team.seekers.oj.contest.client.GroupClient;
import team.seekers.oj.contest.client.ProblemClient;
import team.seekers.oj.contest.client.SubmissionClient;
import team.seekers.oj.contest.client.UserClient;
import team.seekers.oj.contest.converter.ContestConvertUtils;
import team.seekers.oj.contest.dto.*;
import team.seekers.oj.contest.entity.ContestDO;
import team.seekers.oj.contest.entity.ContestListDO;
import team.seekers.oj.contest.enums.ContestOpennessEnum;
import team.seekers.oj.homework.conventer.HomeworkConverter;
import team.seekers.oj.homework.conventer.HomeworkListConverter;
import team.seekers.oj.homework.dao.HomeworkDao;
import team.seekers.oj.homework.dao.HomeworkListDao;
import team.seekers.oj.homework.dto.*;
import team.seekers.oj.homework.entity.HomeworkDO;
import team.seekers.oj.homework.entity.HomeworkListDO;
import team.seekers.oj.homework.enums.HomeworkStatusEnum;
import team.seekers.oj.submit.dto.SubmissionCreateReqDTO;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;


@Slf4j
@Service
public class HomeworkService {

    @Autowired
    private HomeworkDao homeworkDao;

    @Autowired
    private HomeworkListDao homeworkListDao;

    @Autowired
    private HomeworkConverter homeworkConverter;

    @Autowired
    private HomeworkListConverter homeworkListConverter;

    @Autowired
    private ProblemClient problemClient;

    @Autowired
    private SubmissionClient submissionClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private GroupClient groupClient;

    @Autowired
    private RedisUtils redisUtils;


    /**
     * 创建一个编程题目的代码提交
     * @param reqDTO
     * @return
     */
    public String createSubmission(HomeworkSubmissionCreateReqDTO reqDTO) throws IOException, ClassNotFoundException {
        HomeworkDO homeworkDO = queryHomeworkAndValidate(reqDTO.getHomeworkId(), reqDTO.getUserId());

        // TODO: 判断该用户是否在这个作业群组中

        HomeworkProblemListDTO homeworkProblemListDTO = homeworkDO.getProblemById(reqDTO.getProblemIndex());
        String problemCode = homeworkProblemListDTO.getProblemCode();
        SubmissionCreateReqDTO submissionCreateReqDTO = SubmissionCreateReqDTO.builder()
                .problemCode(problemCode)
                .judgeTemplateId(reqDTO.getJudgeTemplateId())
                .code(reqDTO.getCode())
                .zipFileId(reqDTO.getZipFileId())
                .userId(reqDTO.getUserId())
                .ipv4(reqDTO.getIpv4())
                .build();
        long submissionId = submissionClient.create(0, submissionCreateReqDTO);
        return Long.toHexString(submissionId);
    }


    public PageResult<HomeworkListDTO> page(HomeworkListReqDTO reqDTO) {
        LambdaQueryChainWrapper<HomeworkListDO> query = homeworkListDao.lambdaQuery()
                .orderByDesc(HomeworkListDO::getGmtStart);
        if (reqDTO.getStudentId() != null) {
            // 查询参加的所有群组
            List<Long> groups = userClient.queryParticipateGroup(reqDTO.getStudentId());
            // 查询所有群组绑定的作业
            query.and(
                    homework -> {
                        for (Long groupId : groups) {
                            List<Long> homeworks = groupClient.queryParticipateHomework(groupId);
                            for (Long homeworkId : homeworks) {
                                homework.or().eq(HomeworkListDO::getId, homeworkId);
                            }
                        }
                        homework.or().eq(HomeworkListDO::getId, null);
                    }
            );
        } else if (reqDTO.getTeacherId() != null){
            // 是老师的话就直接查询了
            query.eq(HomeworkListDO::getUserId, reqDTO.getTeacherId());
        }
        if(reqDTO.getCourseId() != null){
            query.eq(HomeworkListDO::getCourseId, reqDTO.getCourseId());
        }
        Page<HomeworkListDO> pageResult = query.page(new Page<>(reqDTO.getPageNow(), reqDTO.getPageSize()));
        List<HomeworkListDTO> homeworkListDTOS = homeworkListConverter.to(pageResult.getRecords());
        // 数据填充 TODO：想办法删掉优化
        for (HomeworkListDTO homeworkListDTO : homeworkListDTOS) {
            if(new Date().before(homeworkListDTO.getGmtStart())){
                homeworkListDTO.setStatus(HomeworkStatusEnum.WAIT.getType());
            }else if(new Date().after(homeworkListDTO.getGmtEnd())){
                homeworkListDTO.setStatus(HomeworkStatusEnum.END.getType());
            }else {
                homeworkListDTO.setStatus(HomeworkStatusEnum.OPEN.getType());
            }
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            homeworkListDTO.setGmtStartString(simpleDateFormat.format(homeworkListDTO.getGmtStart()));
            homeworkListDTO.setGmtEndString(simpleDateFormat.format(homeworkListDTO.getGmtEnd()));
        }
        return new PageResult<>(pageResult.getPages(), homeworkListDTOS);
    }

    public HomeworkDTO query(Long homeworkId) {
        HomeworkDO homeworkDO = homeworkDao.lambdaQuery().select(
                HomeworkDO::getId,
                HomeworkDO::getTitle,
                HomeworkDO::getCourseId,
                HomeworkDO::getGmtStart,
                HomeworkDO::getGmtEnd,
                HomeworkDO::getUserId,
                HomeworkDO::getProblems,
                HomeworkDO::getParticipantGroups
        ).eq(HomeworkDO::getId, homeworkId).one();
        AssertUtils.notNull(homeworkDO, ApiExceptionEnum.CONTEST_NOT_FOUND);

        // 判断作业可见性
        if (homeworkDO.getGmtStart().after(new Date())) {
            throw new ApiException(ApiExceptionEnum.CONTEST_NOT_BEGIN);
        }
        return homeworkConverter.to(homeworkDO);

    }


    private HomeworkDO queryHomeworkAndValidate(long homeworkId, long userId) {
        HomeworkDO homeworkDO = homeworkDao.lambdaQuery().select(
                HomeworkDO::getId,
                HomeworkDO::getGmtStart,
                HomeworkDO::getGmtEnd,
                HomeworkDO::getUserId,
                HomeworkDO::getProblems,
                HomeworkDO::getParticipantGroups
        ).eq(HomeworkDO::getId, homeworkId).one();
        AssertUtils.notNull(homeworkDO, ApiExceptionEnum.CONTEST_NOT_FOUND);

        if (homeworkDO.getGmtStart().after(new Date())) {
            throw new ApiException(ApiExceptionEnum.CONTEST_NOT_BEGIN);
        }
        return homeworkDO;
    }
}